<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/12/17/017
 * Time: 11:10
 */

namespace App\Models;


use App\Http\Common\Lib\Common;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Schema;

class BaseModel extends Model
{
	protected $guarded = [];
	//protected $fillable = ['*'];

	protected $validatorName;

	/**
	 * 获取数据表所有的字段
	 * @return mixed
	 */
	public function getColumns()
	{
		$cols = Schema::getColumnListing($this->getTable());
		return $cols;
	}

	/**
	 * 设置model的值
	 * @param object $model
	 * @param array $values
	 * @return object
	 */
	public function setData(array $values)
	{
		$cols = $this->getColumns();
		foreach ($values as $key => $value) {
			if (in_array($key, $cols)) {
				$this->$key = $value;
			}
		}
		return $this;
	}

	/**
	 * 表单数据验证
	 * @param $data 需要验证的数据
	 * @param $scene 场景
	 * @return array
	 */
	public function validateData($data, $scene)
	{
		$class = '\\App\\Validator\\' . $this->validatorName;
		$validator = new $class();
		$res = $validator->checkInput($data, $scene);
		return Common::dataFormat($res['status'], $res['msg'], $res['data']);
	}

	/**
	 * 判断某个字段的值是否唯一
	 * @param $col 字段名
	 * @param $value 字段值
	 * @param array $where 额外条件
	 * @return bool
	 */
	public function checkUnique($col, $value, $where = [])
	{
		$count = $this->where($col, $value)->where(function ($query) use ($where) {
			if (!empty($where)) {
				$query->where($where);
			}
		})->count();
		if ($count == 0) {
			return true;
		}
		return false;
	}

	/**
	 * 修改状态
	 * @param $id
	 * @param $opt delete:删除,forbidden:禁用,recovery:正常
	 * @return array
	 */
	public function changeStatus($id, $opt)
	{
		$opts = ['delete', 'forbidden', 'recovery'];
		$opt = strtolower($opt);
		if (!in_array($opt, $opts)) {
			return Common::dataFormat(config('statusInfo.status.fail'), '操作方法不合法');
		}
		$item = $this->where($this->primaryKey, $id)->first();
		if (!$item) {
			return Common::dataFormat(config('statusInfo.status.notFound'), config('statusInfo.msg.notFound'));
		}
		switch ($opt) {
			case 'delete':
				$item->status = -1;
				break;
			case 'forbidden':
				$item->status = 0;
				break;
			case 'recovery':
				$item->status = 1;
				break;
		}
		$res = $item->save();
		if ($res) {
			return Common::dataFormat(config('statusInfo.status.success'), config('statusInfo.msg.success'));
		} else {
			return Common::dataFormat(config('statusInfo.status.fail'), config('statusInfo.msg.fail'));
		}
	}

	/**
	 * 修改某个字段的值
	 * @param $id
	 * @param $col
	 * @param $value
	 * @param array $where
	 * @param null $scene
	 * @return array
	 */
	public function changeColumn($id, $col, $value, $where = [], $scene = null)
	{
		//数据验证
		if ($scene) {
			$input = [
				$this->primaryKey => $id,
				$col => $value,
			];
			$validateRes = $this->validateData($input, $scene);
			if ($validateRes['status'] != config('statusInfo.status.success')) {
				return Common::dataFormat($validateRes['status'], $validateRes['msg']);
			}
		}

		$item = $this->where($this->primaryKey, $id)
			->where(function ($query) use ($where) {
				if ($where) {
					$query->where($where);
				}
			})->first();
		if (!$item) {
			return Common::dataFormat(config('statusInfo.status.notFound'), config('statusInfo.msg.notFound'));
		}
		$item->{$col} = $value;
		$res = $item->save();
		if ($res) {
			return Common::dataFormat(config('statusInfo.status.success'), config('statusInfo.msg.success'));
		} else {
			return Common::dataFormat(config('statusInfo.status.fail'), config('statusInfo.msg.fail'));
		}
	}

	/**
	 * 分页
	 * @param int $page 页数
	 * @param int $pageSize 每页数据量
	 * @param $where 筛选条件
	 * @param string $fields 字段
	 * @param array $order 排序['id'=>'desc']
	 * @param mixed $with 关联(数组，字符串)
	 * @return array
	 */
	public function getPages($page = 1, $pageSize = 10, $where, $fields = '*', $order = [], $with = null)
	{
		$query = $this->where($this->primaryKey, '>', 0);
		if ($where) {
			//$query = $query->where($where);
			$query = $this->buildWhere($query, $where);
		}
		$count = $query->count();
		if ($count == 0) {
			return Common::dataFormat(200, 'success', ['page' => $page, 'pageSize' => $pageSize, 'totalCount' => $count, 'totalPages' => 0, 'pages' => null]);
		}
		$query = $query->select($fields);
		if (!empty($order)) {
			/*foreach ($order as $key=>$value){
				$query = $query->orderBy($key,$value);
			}*/
			$query = $this->buildOrderBy($query, $order);
		}
		if ($with) {
			$query = $query->with($with);
		}
		$pages = $query->skip(($page - 1) * $pageSize)
			->take($pageSize)
			->get();
		$totalPages = ceil($count / $pageSize);
		return Common::dataFormat(200, 'success', ['page' => $page, 'pageSize' => $pageSize, 'totalCount' => $count, 'totalPages' => $totalPages, 'pages' => $pages]);
	}

	/**
	 * 根据id获取一条数据
	 * @param $id
	 * @param string $field
	 * @return array
	 */
	public function findOne($id, $field = '*')
	{
		$res = $this->where($this->primaryKey, $id)->select($field)->first();
		if ($res) {
			return Common::dataFormat(config('statusInfo.status.success'), config('statusInfo.msg.success'), $res);
		} else {
			return Common::dataFormat(config('statusInfo.status.notFound'), config('statusInfo.msg.notFound'));
		}
	}

	/**
	 * 获取下属分类的id
	 * @param int $parentId
	 * @param array $where
	 * @param bool $needSub
	 * @param array $ids
	 * @return array
	 */
	public function getSubIds($parentId = 0, $where = [], $needSub = true, &$ids = [])
	{
		$res = $this->where('parent_id', $parentId)
			->where(function ($query) use ($where) {
				$query->where($where);
			})->pluck('id');
		if ($res) {
			foreach ($res as $key => $value) {
				$ids[] = $value;
				if ($needSub) {
					$this->getSubIds($value, $where, $needSub, $ids);
				}
			}
		}
		return array_unique($ids);
	}

	/**
	 * 构造where条件语句
	 * @param $query
	 * @param array $where
	 * @return mixed
	 */
	protected function buildWhere($query, $where = [])
	{
		if (!$where) {
			return $query;
		}
		foreach ($where as $v1) {

			foreach ($v1 as $k2 => $v2) {
				switch ($k2) {
					case 'and':
						//dd($v2);
						$query = $query->where($v2[0], $v2[1], $v2[2]);
						break;
					case 'like':
						$columns = explode('|', $v2[0]);
						$query = $query->where(function ($qry) use ($columns, $v2) {
							foreach ($columns as $k3 => $column) {
								if (!$column) {
									continue;
								}
								$qry->orWhere($column, 'like', $v2[1]);
								/* if($k3 == 0){
									 $query = $query->where($column,'like',$v2[1]);
								 }else{
									 $query = $query->orWhere($column,'like',$v2[1]);
								 }*/
							}
						});

						break;
					case 'or':
						$query = $query->orWhere($v2);
						break;
					case 'between':
						$query = $query->whereBwtween($v2[0], $v2[1]);
						break;
					case 'notBetween':
						$query = $query->whereNotBetween($v2[0], $v2[1]);
						break;
					case 'in':
						$query = $query->whereIn($v2[0], $v2[1]);
						break;
					case 'notIn':
						$query = $query->whereNotIn($v2[0], $v2[1]);
						break;
					case 'null':
						$query = $query->whereNull($k2);
						break;
					case 'notNull':
						$query = $query->whereNotNull($v2);
						break;
				}
			}
		}
		return $query;
	}

	/**
	 * 构建orderBy语句
	 * @param $query
	 * @param array $orders
	 * @return mixed
	 */
	protected function buildOrderBy($query, $orders = [])
	{
		if (empty($orders)) {
			return $query;
		}
		foreach ($orders as $key => $order) {
			$query = $query->orderBy($key, $order);
		}
		return $query;
	}

	/**
	 * 列表
	 * @param array $where
	 * @param string|array $fields
	 * @param array $order
	 * @return mixed
	 */
	public function getAllList($where=[],$fields='*',$order=[]){
		$query = $this->select($fields);
		if(!empty($where)){
			$this->buildWhere($query,$where);
		}
		if(!empty($order)){
			$this->buildOrderBy($order);
		}
		return $query->get();
	}
}